﻿using System;
using System.Collections.Generic;
using System.Net.Sockets.Kcp;
using System.Text;
using System.Threading.Tasks;
using Bouyei.NetFactory;

namespace Server
{
    class Program
    {
        static INetServerProvider serverProvider = null;
        static int port = 16650;
        static Kcp kcp = null;
        static KcpCallback kcpCb = null;
        static Dictionary<int, SegmentToken> clients = null;

        public static void Main(string[] args)
        {
            clients = new Dictionary<int, SegmentToken>();

            serverProvider = NetServerProvider.CreateProvider(256, 4, NetProviderType.Udp);
            serverProvider.ReceivedOffsetHandler += ReceivedOffsetHandler;

            const int conv = 123;
            kcpCb = new KcpCallback();
            kcpCb.OnOutput += OnOutput;
            kcp = new Kcp(conv, kcpCb);
            kcp.NoDelay(1, 10, 2, 1);//fast
            kcp.WndSize(64, 64);
            kcp.SetMtu(512);

            if (serverProvider.Start(port))
            {
                Console.WriteLine("服务器启动成功");
            }
            Task.Run(async () =>
            {
                try
                {
                    while (true)
                    {
                        kcp.Update(DateTime.UtcNow);

                        int len;
                        while ((len = kcp.PeekSize()) > 0)
                        {
                            var buffer = new byte[len];
                            if (kcp.Recv(buffer) >= 0)
                            {
                                Console.WriteLine("取出kcp收到的消息");
                                string msg = Encoding.UTF8.GetString(buffer);
                                Console.WriteLine(msg + " 服务器时间:" + GetTimeStamp());

                                msg = "服务器时间:" + GetTimeStamp();
                                kcp.Send(Encoding.UTF8.GetBytes(msg));
                                Console.WriteLine("把需要发送的消息放进kcp");
                            }
                        }

                        await Task.Delay(5);
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                }
            });

            Console.ReadKey();
            serverProvider.Dispose(); 
        }

        static void OnOutput(Memory<byte> buffer)
        {
            Console.WriteLine("把kcp中需要发送的消息发送出去");
            foreach (KeyValuePair<int, SegmentToken> keyValuePair in clients)
            {
                serverProvider.Send(new SegmentToken(keyValuePair.Value.sToken, buffer.ToArray()));
            }
        }

        static void ReceivedOffsetHandler(SegmentToken session)
        {
            Console.WriteLine("接收消息放入kcp");
            if (!clients.ContainsKey(session.sToken.TokenId))
            {
                clients.Add(session.sToken.TokenId, session);
            }
            byte[] buffer = new byte[session.Data.size];
            Buffer.BlockCopy(session.Data.buffer, session.Data.offset, buffer, 0, session.Data.size);
            kcp.Input(buffer);
        }

        static long GetTimeStamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds);
        }
    }
}